#include "at32f413_wk_config.h"
#include "wk_system.h"
#include "sys.h"
#include "usmart.h"
#include "log.h"
#include "drv_rtc.h"
#include "version.h"
#include "led.h"
#include "key.h"
#include "lcd_draw.h"
#include "lcd_char.h"
#include "sgl_core.h"
#include "sgl_init.h"
#include "user_key.h"
#include "multi_timer.h"
#include "drv_timer.h"
#include "user_display.h"
#include "user_memory.h"


#undef	LOG_LVL
#define LOG_LVL		LOG_LVL_DEBUG
#include "log.h"

USER_PARA sys_user_para;

extern uint32_t wk_timebase_get(void);
void wk_system_init(void);
void creat_user_wdt_reset_task(void);
void creat_para_set_auto_exit_task(void);
void rgb_led_ctrl(void);




/* RAM扩充为64KB，同时flash降低至224KB */
#define EXTEND_SRAM 0x00
void extend_sram(void)
{
  /* check if ram has been set to expectant size, if not, change eopb0 */
  if(((USD->eopb0) & 0xFF) != EXTEND_SRAM)
  {
    flash_unlock();
    /* erase user system data bytes */
    flash_user_system_data_erase();
    
    /* change sram size */
    flash_user_system_data_program((uint32_t)&USD->eopb0, EXTEND_SRAM);
    
    /* system reset */
    nvic_system_reset();
  }
}



static void user_test_task(void)
{
    #if 0

    #endif
}
static struct Timer user_test_timer; 
void creat_user_test_task(void)
{
	timer_init(&user_test_timer, user_test_task, 1000, LOOP_FOREVER);
	timer_start(&user_test_timer);
}


/**
 * @description: 用户UI显示任务
 * @return {*}
 */
static void user_ui_task(void)
{
    sgl_task_handle();
}
static struct Timer user_ui_timer; 
void creat_user_ui_task(void)
{
	timer_init(&user_ui_timer, user_ui_task, 30, LOOP_FOREVER);
	timer_start(&user_ui_timer);
}

int main(void)
{
    wk_system_init();
    led_gpio_init();
	key_gpio_init();
    usmart_init(200);
	timer10_base_init();
    log_time_register(wk_timebase_get);
    /* 显示版本号 */
    version();
	log_e("system_core_clock = %ld", system_core_clock);
	
	/* 检查SRAM是否是64K */
	if(((USD->eopb0) & 0xFF) == EXTEND_SRAM)
		log_d("SRAM = 64KB");
	else
		log_e("SRAM check error.");
		
    delay_ms(100);

    /* 加载用户配置参数 */
    read_user_config_para();
    memcpy(&sys_user_para.cfg_para, &sys_user_memory.cfg_para, sizeof(SYS_CFG));
    sys_user_para.rgb_light_color = sys_user_para.cfg_para.rgb_bright * 255 / 100;
    sys_user_para.rgb_flow_step_time = sys_user_para.cfg_para.flow_time * 10 / sys_user_para.cfg_para.rgb_length / 3;
    /* 关闭所有RGB灯带 */
    wk_dma1_channel1_init(RGB_LENGTH_MAX);
    memset(rgb_pwm_buffer, 0, sizeof(rgb_pwm_buffer));
    set_all_led_same_color(0, RGB_LENGTH_MAX);
    /* 开启dma传输 */
	timer1_dma_transfer_ctrl(ON);
    delay_ms(100);
    memset(rgb_pwm_buffer, 0, sizeof(rgb_pwm_buffer));
 
	/* LCD初始化 */
	lcd_init();
	lcd_clear(BLACK);
	lcd_back_light_set(0);	
	/* GUI显示初始化 */
	user_sgl_init();
    /* 配置用户当前使用的芯片传输数量 */
    wk_dma1_channel1_init(sys_user_para.cfg_para.rgb_length);
    timer1_dma_transfer_ctrl(ON);

	/* 显示默认界面(传感器状态检测) */
    user_display_init();

	/* 创建显示任务 */
	creat_user_ui_task();
    /* 创建按键扫描任务 */
	creat_user_button_task();
    /* 创建看门狗复位任务 */
    creat_user_wdt_reset_task();

    /* 创建用户参数设置页面自动退出任务 */
//    creat_para_set_auto_exit_task();
    /*  创建测试任务 */
//    creat_user_test_task();

	while(1)
	{
        /* 系统调度器 */
        timer_loop();
        /* RGB灯带控制 */
        rgb_led_ctrl();
	}
}

static uint16_t sensor_a_hold_on_sta = 0;
static uint16_t sensor_b_hold_on_sta = 0;

/**
 * @description: RGB灯带控制
 * @return {*} null
 */
void rgb_led_ctrl(void)
{
    uint16_t i = 0;
    uint32_t rgb_color = 0;
    
    /* 参数设置时不对流水灯带进行流动控制 */
    if(sys_user_para.para_id != PARA_ID_NULL)
    {
        sys_user_para.sensor_a_trig_en = FALSE;
        sys_user_para.rgb_a_hold_cnt = 0;
        sys_user_para.rgb_a_flow_cnt = 0;
        sensor_a_hold_on_sta = 0;
        memset(sys_user_para.rgb_a_sta_buff, 0, sizeof(sys_user_para.rgb_a_sta_buff));

        sys_user_para.sensor_b_trig_en = FALSE;
        sys_user_para.rgb_b_hold_cnt = 0;
        sys_user_para.rgb_b_flow_cnt = 0;
        sensor_b_hold_on_sta = 0;
        memset(sys_user_para.rgb_b_sta_buff, 0, sizeof(sys_user_para.rgb_b_sta_buff));
        return;
    }
    /* 100us 执行一次RGB灯带流动任务 */
    if(sys_user_para.rgb_flow_step_en)
    {
        sys_user_para.rgb_flow_step_en = 0;
        if(sys_user_para.sensor_a_trig_en)
        {
            /* 当前流动次数未达到最大值 */
            if(sys_user_para.rgb_a_flow_cnt < (sys_user_para.cfg_para.rgb_length * 3))
            {
                sys_user_para.rgb_a_flow_cnt++;
                for(i = 0; i < (sys_user_para.cfg_para.rgb_length * 3); i++)
                {
                    if(i < sys_user_para.rgb_a_flow_cnt)
                        sys_user_para.rgb_a_sta_buff[i] = 1;
                    else
                        sys_user_para.rgb_a_sta_buff[i] = 0;
                }
                sys_user_para.rgb_a_hold_cnt = 0;
            }
            else
            {
                /* 流动亮结束后，进入全亮保持状态 */
                if(sensor_a_hold_on_sta == FALSE)
                    sensor_a_hold_on_sta = TRUE;
                else
                {
                    /* 全亮保持时间到后，开始进入流动熄灭状态 */
                    if(sys_user_para.rgb_a_hold_cnt >= sys_user_para.cfg_para.all_on_time)
                    {
                        if(sys_user_para.rgb_a_flow_cnt < (sys_user_para.cfg_para.rgb_length * 3 * 2))
                        {
                            sys_user_para.rgb_a_flow_cnt++;
                            for(i = 0; i < (sys_user_para.cfg_para.rgb_length * 3); i++)
                            {
                                if(i < (sys_user_para.rgb_a_flow_cnt - sys_user_para.cfg_para.rgb_length * 3))
                                    sys_user_para.rgb_a_sta_buff[i] = 0;
                            }
                        }
                        else
                        {
                            /* 流动熄灭结束 */
                            sys_user_para.rgb_a_hold_cnt = 0;
                            sys_user_para.rgb_a_flow_cnt = 0;
                            sys_user_para.sensor_a_trig_en = 0;
                            sensor_a_hold_on_sta = FALSE;
                            memset(sys_user_para.rgb_a_sta_buff, 0, sizeof(sys_user_para.rgb_a_sta_buff));
                        }
                    }
                }
            }
        }
#if 1
        if(sys_user_para.sensor_b_trig_en)
        {
            /* 当前流动次数未达到最大值 */
            if(sys_user_para.rgb_b_flow_cnt < (sys_user_para.cfg_para.rgb_length * 3))
            {
                sys_user_para.rgb_b_flow_cnt++;
                for(i = 0; i < (sys_user_para.cfg_para.rgb_length * 3); i++)
                {
                    if(i < sys_user_para.rgb_b_flow_cnt)
                        sys_user_para.rgb_b_sta_buff[sys_user_para.cfg_para.rgb_length*3 - 1 - i] = 1;
                    else
                        sys_user_para.rgb_b_sta_buff[sys_user_para.cfg_para.rgb_length*3 - 1 - i] = 0;
                }
                sys_user_para.rgb_b_hold_cnt = 0;
            }
            else
            {
                /* 流动亮结束后，进入全亮保持状态 */
                if(sensor_b_hold_on_sta == FALSE)
                    sensor_b_hold_on_sta = TRUE;
                else
                {
                    /* 全亮保持时间到后，开始进入流动熄灭状态 */
                    if(sys_user_para.rgb_b_hold_cnt >= sys_user_para.cfg_para.all_on_time)
                    {
                        if(sys_user_para.rgb_b_flow_cnt < (sys_user_para.cfg_para.rgb_length * 3 * 2))
                        {
                            sys_user_para.rgb_b_flow_cnt++;
                            for(i = 0; i < (sys_user_para.cfg_para.rgb_length * 3); i++)
                            {
                                if(i < (sys_user_para.rgb_b_flow_cnt - sys_user_para.cfg_para.rgb_length * 3))
                                    sys_user_para.rgb_b_sta_buff[sys_user_para.cfg_para.rgb_length*3 - 1 - i] = 0;
                            }
                        }
                        else
                        {
                            /* 流动熄灭结束 */
                            sys_user_para.rgb_b_hold_cnt = 0;
                            sys_user_para.rgb_b_flow_cnt = 0;
                            sys_user_para.sensor_b_trig_en = 0;
                            sensor_b_hold_on_sta = FALSE;
                            memset(sys_user_para.rgb_b_sta_buff, 0, sizeof(sys_user_para.rgb_b_sta_buff));
                        }
                    }
                }
            }
        }

        if(sys_user_para.sensor_a_trig_en  ||  sys_user_para.sensor_b_trig_en)
        {
            for(i = 0; i < sys_user_para.cfg_para.rgb_length; i++)
            {
                rgb_color = 0;
                if(sys_user_para.rgb_a_sta_buff[i*3 + 0] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 0] == 1)      //G
                    rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 8;
                if(sys_user_para.rgb_a_sta_buff[i*3 + 1] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 1] == 1)      //R
                    rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 16;
                if(sys_user_para.rgb_a_sta_buff[i*3 + 2] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 2] == 1)      //B
                    rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 0;
                change_color_to_bit(rgb_color, rgb_pwm_buffer + i*24);
            }
        }
#endif
    }

    if(sys_user_para.rgb_hold_time_flag)
    {
        sys_user_para.rgb_hold_time_flag = FALSE;
        if(sensor_a_hold_on_sta)
        {
            if(sys_user_para.rgb_a_hold_cnt < sys_user_para.cfg_para.all_on_time)
            {
                sys_user_para.rgb_a_hold_cnt += 1;
            }
#if 0
            else
            {
				log_d("A hold on over");

                sys_user_para.rgb_a_hold_cnt = 0;
                sys_user_para.rgb_a_flow_cnt = 0;
                sensor_a_hold_on_sta = 0;
                memset(sys_user_para.rgb_a_sta_buff, 0, sizeof(sys_user_para.rgb_a_sta_buff));
                if(sys_user_para.sensor_a_trig_en  ||  sys_user_para.sensor_b_trig_en)
                {
                    for(i = 0; i < sys_user_para.cfg_para.rgb_length; i++)
                    {
                        rgb_color = 0;
                        if(sys_user_para.rgb_a_sta_buff[i*3 + 0] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 0] == 1)      //G
                            rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 8;
                        if(sys_user_para.rgb_a_sta_buff[i*3 + 1] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 1] == 1)      //R
                            rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 16;
                        if(sys_user_para.rgb_a_sta_buff[i*3 + 2] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 2] == 1)      //B
                            rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 0;
                        
                        change_color_to_bit(rgb_color, rgb_pwm_buffer + i*24);
                    }
                }
                sys_user_para.sensor_a_trig_en = 0;
            }
#endif
        }

        if(sensor_b_hold_on_sta)
        {
            if(sys_user_para.rgb_b_hold_cnt < sys_user_para.cfg_para.all_on_time)
            {
                sys_user_para.rgb_b_hold_cnt += 1;
            }
#if 0
            else
            {
                sys_user_para.rgb_b_hold_cnt = 0;
                sys_user_para.rgb_b_flow_cnt = 0;
                sensor_b_hold_on_sta = 0;
                memset(sys_user_para.rgb_b_sta_buff, 0, sizeof(sys_user_para.rgb_b_sta_buff));
                if(sys_user_para.sensor_a_trig_en  ||  sys_user_para.sensor_b_trig_en)
                {
                    for(i = 0; i < sys_user_para.cfg_para.rgb_length; i++)
                    {
                        rgb_color = 0;
                        if(sys_user_para.rgb_a_sta_buff[i*3 + 0] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 0] == 1)      //G
                            rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 8;
                        if(sys_user_para.rgb_a_sta_buff[i*3 + 1] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 1] == 1)      //R
                            rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 16;
                        if(sys_user_para.rgb_a_sta_buff[i*3 + 2] == 1  ||  sys_user_para.rgb_b_sta_buff[i*3 + 2] == 1)      //B
                            rgb_color |= ((uint32_t)sys_user_para.rgb_light_color) << 0;
                        change_color_to_bit(rgb_color, rgb_pwm_buffer + i*24);
                    }
                }
                sys_user_para.sensor_b_trig_en = 0;
            }
#endif
        }
    }
}


/**
 * @description: 用户看门狗复位回调函数,3s,同时检测系统配置参数是否被修改，修改自动保存
 * @return {*} null
 */
static void user_wdt_reset_callback(void)
{
    uint32_t crc_old = 0, crc_new = 0;
    uint32_t len = sizeof(SYS_CFG) / 4;

    crc_new = user_memory_para_crc_check((uint32_t *)&sys_user_para.cfg_para, len);
    crc_old = user_memory_para_crc_check((uint32_t *)&sys_user_memory.cfg_para, len);
    
    if(crc_new != crc_old)
    {
        log_i("system config para changed!");
        memcpy(&sys_user_memory.cfg_para, &sys_user_para.cfg_para, sizeof(SYS_CFG));
        write_user_config_para(&sys_user_memory);
        log_i("system config para save ok!");
    }

    /* 看门狗复位 */
    wdt_counter_reload();
}
static struct Timer user_wdt_reset_timer; 
void creat_user_wdt_reset_task(void)
{
    wdt_counter_reload();
	timer_init(&user_wdt_reset_timer, user_wdt_reset_callback, 3000, LOOP_FOREVER);
	timer_start(&user_wdt_reset_timer);
}

void user_rgb_ctrl_set(uint16_t rst)
{
    static PA_ID old_para_id = PARA_ID_NULL;
    uint32_t rgb_color = 0;
    if(sys_user_para.para_id != old_para_id  ||  rst)
    {
        if(sys_user_para.para_id == PARA_ID_NULL)
        {
            wk_dma1_channel1_init(sys_user_para.cfg_para.rgb_length);
            timer1_dma_transfer_ctrl(ON);
            set_all_led_same_color(0x000000, sys_user_para.cfg_para.rgb_length);
            memset((uint8_t *)rgb_pwm_buffer + sys_user_para.cfg_para.rgb_length * 24 * 2, 0, 400*2);
        }
        else if(sys_user_para.para_id != PARA_ID_NULL  &&  old_para_id == PARA_ID_NULL)
        {
            wk_dma1_channel1_init(RGB_LENGTH_MAX);
            timer1_dma_transfer_ctrl(ON);
            rgb_color = ((uint32_t)sys_user_para.rgb_light_color << 16) + ((uint32_t)sys_user_para.rgb_light_color << 8) + sys_user_para.rgb_light_color;
            set_rgb_led_same_color(rgb_color, sys_user_para.cfg_para.rgb_length);
            memset((uint8_t *)rgb_pwm_buffer + RGB_LENGTH_MAX * 24 * 2, 0, 400*2);
        }

        old_para_id = sys_user_para.para_id;
    }
}


/* 用户参数设置自动退出计数 */
static uint16_t auto_exit_cnt = 0;
/**
 * @description: 用户参数设置自动退出计数清除
 * @return {*}
 */
void para_set_auto_exit_clear(void)
{
    auto_exit_cnt = 0;
}
void para_set_auto_exit_task_callback(void)
{
    #define AUTO_EXIT_TIME  (5 * 1000)
    if(sys_user_para.para_id != PARA_ID_NULL)
    {
        if(auto_exit_cnt < (AUTO_EXIT_TIME/500))
            auto_exit_cnt++;
        else
        {
            sys_user_para.para_id = PARA_ID_NULL;
            user_para_set_display(sys_user_para.para_id, 0);
            /* 关闭所有RGB LED */
            set_all_led_same_color(0, RGB_LENGTH_MAX);
            delay_ms(50);
            user_rgb_ctrl_set(1);
            log_d("user para set auto exit!");

            set_all_led_same_color(0, RGB_LENGTH_MAX);
        }
    }
}
static struct Timer user_auto_exit_timer; 
void creat_para_set_auto_exit_task(void)
{
	timer_init(&user_auto_exit_timer, para_set_auto_exit_task_callback, 500, LOOP_FOREVER);
	timer_start(&user_auto_exit_timer);
}




void wk_system_init(void)
{
    /* system clock config. */
    wk_system_clock_config();

    /* config periph clock. */
    wk_periph_clock_config();

    /* init debug function. */
    wk_debug_config();

    /* nvic config. */
    wk_nvic_config();

    /* timebase config. */
    wk_timebase_init();

    /* init usart1 function. */
    wk_usart1_init();

    /* init usart3 function. */
//    wk_usart3_init();

    /* init tmr1 function. */
    wk_tmr1_init();

    wk_tmr11_init();
 /* init dma1 channel1 */
//    wk_dma1_channel1_init(sys_user_para.cfg_para.rgb_length);

    /* init wdt function. */
    wk_wdt_init();

}
